using CPRMulti.Tools;
using HHHFramework;
using HHHTool;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using UnityEngine;
using UnityEngine.UI;
using VRCPRServer.NetWork;
public class ServerManager : MonoSingleton<ServerManager>
{
    public delegate void RecivePadMessageDelegate();
    public delegate void SendPadMessageDelegate();
    public NetManger manager = null;//server
    public TcpNetManager TcpnetManager;//连接模拟人Socket类
    private Thread thread;
    public bool start = false;
    private bool padIsRuning = false;
    public bool isPressUiEnable = false;
    public bool isShowPartial = false;//是否显示局部视角
    public bool isShowVitalSigns = false;//是否显示什么体征
  
    public int clientNumber = 0;

    #region 接受pad命令 
    // Start is called before the first frame update
    public RecivePadMessageDelegate padReciveMessageStart;//开始
    public RecivePadMessageDelegate padReciveMessageBack;//结束
    public RecivePadMessageDelegate padReciveMessagePause;//暂停
    public RecivePadMessageDelegate padReciveMessageSkipCurrentStep;//跳过当前步骤

    public RecivePadMessageDelegate padReciveMessageAEDArrive;//aed到达
    public RecivePadMessageDelegate padReciveMessage120Arrive;//120到达
    public RecivePadMessageDelegate padReciveMessageTeachCPR;//开始播放教学视频

    public RecivePadMessageDelegate padReciveMessageShowVitalSigns;//显示生命体征
    public RecivePadMessageDelegate padReciveMessageHideVitalSigns;//隐藏生命体征  暂时没有内容
    /// <summary>
    /// 显示操作数据
    /// </summary>
    public RecivePadMessageDelegate padReciveMessageShowOperation;//  
    /// <summary>
    /// 隐藏操作数据
    /// </summary>
    public RecivePadMessageDelegate padReciveMessageHideOperation;//
    /// <summary>
    /// 显示 局部视角
    /// </summary>
    public RecivePadMessageDelegate padReciveMessageShowPartial;//
    /// <summary>
    /// 隐藏 局部视角
    /// </summary>
    public RecivePadMessageDelegate padReciveMessageHidePartial;//

    public RecivePadMessageDelegate padReciveMessageOpenSubwayScene;//打开subway场景
    public RecivePadMessageDelegate padReciveMessageOpenFireScene;//打开火灾场景
    public RecivePadMessageDelegate padReciveMessageOpenEarthquakeScene;//打开地震场景
    public RecivePadMessageDelegate padRecivemessageOpenDrowningScene;//打开溺水场景
    public RecivePadMessageDelegate padReciveMessageOpenTrafficAccidentScene;//打开车祸场景


    public RecivePadMessageDelegate padReciveMessagePreviewSubwayScene;//预览地铁场景
    public RecivePadMessageDelegate padReciveMessagePreviewFireScene;//预览火灾场景
    public RecivePadMessageDelegate padReciveMessagePreviewEarthquakeScene;//预览地震场景
    public RecivePadMessageDelegate padReciveMessagePreviewDrowningScene;//预览溺水场景
    public RecivePadMessageDelegate padReciveMessagePreviewTrafficAccidentScene;//预览车祸场景
    public RecivePadMessageDelegate padReciveMessageReconnection;//重新连接 发送当前的状态给pad
    #endregion

    #region 向pad 发送的命令
    public bool isSceneChooseEnable = false;

    /// <summary>
    /// 是否可以选择场景UI
    /// </summary>
    public SendPadMessageDelegate padSendMessageSceneChooseEnable;
    public SendPadMessageDelegate padSendMessageSceneChooseDisEnable;
    public SendPadMessageDelegate sendMessageToPadOpenTeachingCPR;
    public SendPadMessageDelegate sendMessageToPadHideTeachingCPR;
    #endregion

    #region 模拟人
    string localIP = "";
    string localPort = "";
    ReadINI readINI = new ReadINI();
    string iniPath = Application.streamingAssetsPath + "/DeviceStatus.ini";
    public Action<float> modelPressAction;
    private IPEndPoint modelIpendPoint;
    #endregion
    void Start()
    {
        TcpnetManager = TcpNetManager.Instance;

        CreateServer();
        start = true;
        SendMessageToPad("硬件未连接");

        SetSendMessageToPadDelegate();

        Invoke("ConnectFirstModel", 2f);
    }
    public void ConnectFirstModel() {
        localIP = readINI.ReadIPIni("LocalIP", iniPath);
        localPort = readINI.ReadIPIni("LocalPort", iniPath);

        var modelInfo = new ModelInfo() { modelID = "01", isMainModel = true, ipAddress = localIP, port = localPort, connect = true };
        //MultipleSimulacrumUI.Instance.AddOrUpdateStudent(modelInfo);
    }
    void SetSendMessageToPadDelegate() {
        sendMessageToPadOpenTeachingCPR = new SendPadMessageDelegate(() => {
            SendMessageToPad("显示教学按钮");
        });
        sendMessageToPadHideTeachingCPR = new SendPadMessageDelegate(() => {
            SendMessageToPad("隐藏教学按钮");
        });
        padSendMessageSceneChooseEnable = new SendPadMessageDelegate(()=> {
            if (isSceneChooseEnable==false) {
                SendMessageToPad("硬件已连接");
                isSceneChooseEnable = true;
            }
        })  ;
        padSendMessageSceneChooseDisEnable = new SendPadMessageDelegate(() => {
            if (isSceneChooseEnable) {
                SendMessageToPad("硬件未连接");
                isSceneChooseEnable = false;
            }          
        });
        padReciveMessageReconnection = new RecivePadMessageDelegate(() => {
            //if (AppManager.Instance.AppStateInfo == AppManager.AppState.硬件检测)
            //{
            //    SendMessageToPad("打开场景选择");
            //}
            //else {
            //    SendMessageToPad("打开场景控制");
            //}
            //if (isSceneChooseEnable)
            //{
            //    SendMessageToPad("硬件已连接");
            //}
            //else {
            //    SendMessageToPad("硬件未连接");
            //}

            if (isPressUiEnable)
            {
                SendMessageToPad("显示操作数据");
            }
            else {
                SendMessageToPad("隐藏操作数据");
            }
            if (isShowPartial) {
                SendMessageToPad("显示局部视角");
            } else {
                SendMessageToPad("隐藏局部视角");
            }
            SendMessageToPad("隐藏教学按钮");
        });

       
    }
    // Update is called once per frame
    void Update()
    {
        if (start)
        {

            if (manager.tcpServer.IsRuning) {

                #region
                ReciveMessage();
                #endregion
                clientNumber = manager.tcpServer.ClientList.Count;

            }
            if (ModelisConnected()) {
               // modelPressAction?.Invoke(TcpnetManager.StudentDic[modelIpendPoint].PressDepth);              
            }

        }
    }

    /// <summary>
    /// 实例化netManager 创建服务器
    /// </summary>
    public void CreateServer()
    {
        manager = new NetManger();
        thread = new Thread(new ThreadStart(ThreadTimer));
        thread.IsBackground = true;
        thread.Start();
        manager.PadConnetState += PadConectedState;
    }   
 
    public void ClientModelStop()
    {
       
    }
    public void ClientModelStart() {

    }
  
    public void AddText(string str)
    {
        
    }

#region pad 
    public void ReciveMessage()
    {
        if (manager.dataBuffer.DataCount == 0)
        {
            return ;
        }
        
        byte[] head = new byte[1];
        byte[] type = new byte[1];
        byte[] msgLength = new byte[2];
        head = manager.dataBuffer.ReadBuffer(1);
        if (head != null)
        {
            if (head[0] == 0xFF)
            {
                type = manager.dataBuffer.ReadBuffer(1);
                if (type != null)
                {
                    msgLength = manager.dataBuffer.ReadBuffer(2);
                    if (msgLength == null)
                    {
                        Debug.Log("msglength null");
                        return;
                    }
                    else
                    {
                        int dataLength = msgLength[0] * 256 + msgLength[1] ;
                        byte[] data = new byte[dataLength];
                       // Debug.Log("获取数据dataLength"+ dataLength);
                        data = manager.dataBuffer.ReadBuffer(dataLength);

                        if (data != null)
                        {
                            string step = string.Empty;
                            byte[] sumDatas = new byte[dataLength + 4];
                            sumDatas[0] = head[0];
                            sumDatas[1] = type[0];
                            sumDatas[2] = msgLength[0];
                            sumDatas[3] = msgLength[1];
                            data.CopyTo(sumDatas, 4);
                            byte sum = Sum1(sumDatas, 0, sumDatas.Length - 1);
                            if (sum == data[dataLength - 1])
                            {
                                MessageCheck(type[0], data);
                            }

                        }
                    }
                }
            }
            else { Debug.Log("type null"); }

        }
        else { Debug.Log(" data null"); }
    }

    private void MessageCheck(byte type, byte[] data)
    {
        data = data.Take(data.Length - 1).ToArray();

        if (type == CommandType.connected)
        {
            if (Enumerable.SequenceEqual(data, CommandData.heartData))
            {
                //Debug.Log("心跳包  fa fb 0 0 0 0");
                return;
            }

            if (Enumerable.SequenceEqual(data, CommandData.isConcentServer))
            {
                padIsRuning = true;
                SendMessageToPad("返回连接成功");
                return;
            }
            if (Enumerable.SequenceEqual(data, CommandData.isDisConcentServer))
            {
                padIsRuning = false;
                ///主动移除自己
                manager.ClearPadClient();
                Debug.LogError("pad 断开连接");
                return;
            }
            if (Enumerable.SequenceEqual(data, CommandData.reconnection))
            {
                padReciveMessageReconnection?.Invoke();
                return;
            }
        }

        if (type == CommandType.padTouchCommand)
        {
            //判断两个集合是否相同
            if (Enumerable.SequenceEqual(data, CommandData.showOperation))
            {
                Debug.Log("打开UI");
                padReciveMessageShowOperation?.Invoke();
            }
            if (Enumerable.SequenceEqual(data, CommandData.hideOperation))
            {
                Debug.LogError("CommandData.hideOperation");
                padReciveMessageHideOperation?.Invoke();
            }

            if (Enumerable.SequenceEqual(data, CommandData.showPartial))
            {
                padReciveMessageShowPartial?.Invoke();
            }
            if (Enumerable.SequenceEqual(data, CommandData.hidePartial))
            {
                padReciveMessageHidePartial?.Invoke();
            }

            if (Enumerable.SequenceEqual(data, CommandData.showVitalSigns))
            {
                
            }
            if (Enumerable.SequenceEqual(data, CommandData.hideVitalSigns))
            {
                
            }

            if (Enumerable.SequenceEqual(data, CommandData.startData))
            {
                Debug.Log("play");
                padReciveMessageStart?.Invoke();
                return;
            }
            if (Enumerable.SequenceEqual(data, CommandData.pauseData))
            {
                Debug.Log("pause");
                padReciveMessagePause?.Invoke();
            }
            if (Enumerable.SequenceEqual(data, CommandData.back))
            {
                Debug.LogError("BACK>>>>>>>>>>>>");
                padReciveMessageBack?.Invoke();
            }
            if (Enumerable.SequenceEqual(data, CommandData.skipData))
            {
                string.Format("<color=green>{0}</color>", "skip");
                padReciveMessageSkipCurrentStep?.Invoke();
            }
            if (Enumerable.SequenceEqual(data, CommandData.aedData))
            {
                padReciveMessageAEDArrive?.Invoke();
            }
            if (Enumerable.SequenceEqual(data, CommandData.data120))
            {
                padReciveMessage120Arrive?.Invoke();
            }
            if (Enumerable.SequenceEqual(data, CommandData.teachingCPRPlay))
            {
                padReciveMessageTeachCPR?.Invoke();
            }
            //预览场景
            if (Enumerable.SequenceEqual(data, CommandData.previewSubwayScene))
            {
                padReciveMessagePreviewSubwayScene?.Invoke();
            }
            if (Enumerable.SequenceEqual(data, CommandData.previewFireScene))
            {
                padReciveMessagePreviewFireScene?.Invoke();
            }
            if (Enumerable.SequenceEqual(data, CommandData.previewEarthquakeScene))
            {
                padReciveMessagePreviewEarthquakeScene?.Invoke();
            }
            if (Enumerable.SequenceEqual(data, CommandData.previewTrafficAccidentScene))
            {
                padReciveMessagePreviewTrafficAccidentScene?.Invoke();
            }
            if (Enumerable.SequenceEqual(data, CommandData.previewDrowningScene))
            {
                padReciveMessagePreviewDrowningScene?.Invoke();
            }
            //打开场景
            if (Enumerable.SequenceEqual(data, CommandData.openSubwayScene))
            {
                padReciveMessageOpenSubwayScene?.Invoke();
            }
            if (Enumerable.SequenceEqual(data, CommandData.openFireScene))
            {
                padReciveMessageOpenFireScene?.Invoke();
            }
            if (Enumerable.SequenceEqual(data, CommandData.openEarthquakeScene))
            {
                padReciveMessageOpenEarthquakeScene?.Invoke();
            }
            if (Enumerable.SequenceEqual(data, CommandData.openTrafficAccidentScene))
            {
                padReciveMessageOpenTrafficAccidentScene?.Invoke();
            }
            if (Enumerable.SequenceEqual(data, CommandData.openDrowningScene))
            {
                padRecivemessageOpenDrowningScene?.Invoke();
            }


        }

        if (type == CommandType.modelConnectInfo)
        {
            ModelInfo modelInfo = SerializeObject.DesrializeByBytes<ModelInfo>(data);
            if (IPAddress.TryParse(modelInfo.ipAddress, out IPAddress address))
            {

                IPEndPoint iPEndPoint = new IPEndPoint(address, Convert.ToInt32(modelInfo.port));
                //if (modelInfo.connect)
                //{
                //    MultipleSimulacrumUI.Instance.AddOrUpdateStudent(modelInfo);
                //}
                //else {
                //    MultipleSimulacrumUI.Instance.RemoveStudent(modelInfo);
                //}
               
            }

        }
        if (type == CommandType.cprDataSet)
        {

        }
        if (type == CommandType.pcReturn)
        {
            if (Enumerable.SequenceEqual(data, CommandData.deviceReady))
            {
               
            }

            if (Enumerable.SequenceEqual(data, CommandData.deviceNotReady))
            {
               
            }

            if (Enumerable.SequenceEqual(data, CommandData.choosePanel))
            {
                
            }

            if (Enumerable.SequenceEqual(data, CommandData.scenePanel))
            {
                
            }
        }
        if(type == CommandType.teachingAudioVolume){
            float volume = SerializeObject.DesrializeByBytes<float>(data);
            AudioListener.volume = volume;
        }

    }

    public void SendMessageToPad(string sendName)
    {
        byte[] data = new byte[9];
        switch (sendName)
        {
            case "Heart":
                {
                    data = SetSendMessage(CommandType.connected, CommandData.heartData);
                }
                break;
            case "硬件未连接":
                {                    

                    data = SetSendMessage(CommandType.pcReturn , CommandData.deviceNotReady);                    
                }
                break;
            case "硬件已连接":
                {
                    Debug.Log("发送硬件连接");
                    data = SetSendMessage(CommandType.pcReturn, CommandData.deviceReady);
                   
                }break;
            case "隐藏操作数据":
                {
                    data = SetSendMessage(CommandType.padTouchCommand, CommandData.hideOperation);
                }
                break;
            case "显示操作数据":
                {
                    data = SetSendMessage(CommandType.padTouchCommand, CommandData.showOperation);
                }
                break;
            case "打开场景控制":
                {
                    data = SetSendMessage(CommandType.pcReturn , CommandData.scenePanel);
                }
                break;
            case "打开场景选择":
                {
                    data = SetSendMessage(CommandType.pcReturn, CommandData.choosePanel);
                }
                break;
            case "显示生命体征":
                {
                    data = SetSendMessage(CommandType.padTouchCommand, CommandData.showVitalSigns);
                }
                break;
            case "隐藏生命体征":
                {
                    data = SetSendMessage(CommandType.padTouchCommand, CommandData.hideVitalSigns);
                }
                break;
            case "显示局部视角":
                {
                    data = SetSendMessage(CommandType.padTouchCommand, CommandData.showPartial);
                }
                break;
            case "隐藏局部视角":
                {
                    data = SetSendMessage(CommandType.padTouchCommand, CommandData.hidePartial);
                }
                break;
            case "返回连接成功":
                {
                    Debug.Log("连接成功返回数据");
                    data = SetSendMessage(CommandType.connected, CommandData.isConcentServer);
                }
                break;
            case "显示教学按钮":
                {
                    data = SetSendMessage(CommandType.pcReturn, CommandData.showTeachCPR);
                }
                break;
            case "隐藏教学按钮":
                {
                    data = SetSendMessage(CommandType.pcReturn, CommandData.HideTeachCPR);
                }
                break;

        }
        manager.tcpServer.SendAll(data);
    }


    public byte[] SetSendMessage(byte order, byte[] msg)
    {
        byte[] data = new byte[9];
        data[0] = 0xFF;
        data[1] = order;
        data[2] = 0x00;
        data[3] = 0x05;
        data[4] = msg[0];
        data[5] = msg[1];
        data[6] = msg[2];
        data[7] = msg[3];
        data[8] = Sum1(data, 0, 9);
        return data;
    }

    public byte[] SetSendModelConnectMessage(ModelInfo modelInfo)
    {
        if (modelInfo == null) return null;

        byte[] bytes = SerializeObject.SerializeToBytes(modelInfo);
        if (bytes == null) return null;
        int length = bytes.Length + 4;
        int dataLength = bytes.Length + 1;

        byte[] datas = new byte[length];
        datas[0] = 0XFF;
        datas[1] = CommandType.modelConnectInfo;
        datas[2] = (byte)(dataLength >> 8);
        datas[3] = (byte)(dataLength & 0xff);
        Array.Copy(bytes, 0, datas, 4, bytes.Length);
        datas[length - 1] = datas.Sum1(0, length - 1);
        return datas;
    }


    public void PadSceneChooseEnable() {
        
    }

    public void PadSceneChooseDisEnable() {
        SendMessageToPad("硬件未连接");
    }

    #region 定时器

    private DateTime heartTime = DateTime.Now;

    private void ThreadTimer()
    {
        while (true)
        {
            if (Math.Abs(DateTime.Now.Second - heartTime.Second) >= 0.9)
            {
                heartTime = DateTime.Now;
                SendMessageToPad("Heart");

            }
            Thread.Sleep(1);
        }
    }
    #endregion

    public bool PadIsConnected()
    {
        return padIsRuning;
    }
    /// <summary>
    /// 查看设置pad状态检测
    /// </summary>
    /// <param name="socket"></param>
    /// <param name="state"></param>
    private void PadConectedState(Socket socket ,bool state) {
        padIsRuning = state;
    }

   

#endregion

    public bool ModelisConnected()
    {
        if (IPAddress.TryParse(localIP, out IPAddress iPAddress) && int.TryParse(localPort, out int port))
        {
            modelIpendPoint = new IPEndPoint(iPAddress, port);
            if (TcpnetManager.SocketDic.ContainsKey(modelIpendPoint))
            {
                if (TcpnetManager.SocketDic[modelIpendPoint].IsConnected) {
                    return true;
                }
                return false;
            }
            return false;

        }
        else {
            Debug.LogError("ipaddress or port is Not Parse");
            return false;
        }
       
       

    }

    public void OnApplicationQuit()
    {
        TcpnetManager.Closed();
        manager.tcpServer.Dispose();
    }
    public static byte Sum1(byte[] bytes, int start, int length)
    {
        byte sum = 0;
        int endIndex = start + length;

        if (bytes == null || bytes.Length < 1)
            new NullReferenceException("bytes is null or bytes length < 1");

        if (start > bytes.Length || endIndex > bytes.Length)
            new IndexOutOfRangeException("bytes Index OutOf Range");

        for (int i = start; i < endIndex; i++)
            sum += bytes[i];

        return sum;
    }

}
#region 在客户端开放这些类
//public class CommandType
//{
//    /// <summary>
//    /// 类型 模拟人连接信息
//    /// </summary>
//    public static readonly byte modelConnectInfo = 0xFA;

//    /// <summary>
//    /// 类型 pad操作指令
//    /// </summary>
//    public static readonly byte padTouchCommand = 0xFB;
//    /// <summary>
//    /// 类型 按压操作数据设置
//    /// </summary>
//    public static readonly byte cprDataSet = 0xFC;
//    /// <summary>
//    /// 连接状态
//    /// </summary>
//    public static readonly byte connected = 0xFD;

//    public static readonly byte pcReturn = 0xFE;

//    public static readonly byte teachingAudioVolume = 0xF0;
//}

//public class CommandData
//{
//    #region connected
//    /// <summary>
//    /// 心跳包
//    /// </summary>
//    public static readonly byte[] heartData = { 0x00, 0x00, 0x00, 0x00 };

//    public static readonly byte[] isConcentServer = { 0x01, 0x01, 0x01, 0x01 };

//    public static readonly byte[] isDisConcentServer = { 0x02, 0x02, 0x02, 0x02 };

//    public static readonly byte[] reconnection = { 0x03, 0x03, 0x03, 0x03 };
//    #endregion

//    #region padTouch  scenePanel AX   sceneChoosePanel BX CX


//    /// <summary>
//    ///显示操作数据
//    /// </summary>
//    public static readonly byte[] showOperation = { 0xA1, 0xA1, 0xA1, 0xA1 };
//    /// <summary>
//    /// 隐藏操作数据
//    /// </summary>
//    public static readonly byte[] hideOperation = { 0xA2, 0xA2, 0xA2, 0xA2 };
//    /// <summary>
//    /// 显示生命体征
//    /// </summary>
//    public static readonly byte[] showVitalSigns = { 0xA3, 0xA3, 0xA3, 0xA3 };
//    /// <summary>
//    /// 隐藏生命体征
//    /// </summary>
//    public static readonly byte[] hideVitalSigns = { 0xA4, 0xA4, 0xA4, 0xA4 };
//    /// <summary>
//    /// 显示局部视角
//    /// </summary>
//    public static readonly byte[] showPartial = { 0xA5, 0xA5, 0xA5, 0xA5 };
//    /// <summary>
//    /// 隐藏局部视角
//    /// </summary>
//    public static readonly byte[] hidePartial = { 0xA6, 0xA6, 0xA6, 0xA6 };

//    public static readonly byte[] startData = { 0xA7, 0xA7, 0xA7, 0xA7 };

//    public static readonly byte[] pauseData = { 0xA8, 0xA8, 0xA8, 0xA8 };

//    public static readonly byte[] back = { 0xA9, 0xA9, 0xA9, 0xA9 };

//    public static readonly byte[] skipData = { 0xAA, 0xAA, 0xAA, 0xAA };

//    public static readonly byte[] aedData = { 0xAB, 0xAB, 0xAB, 0xAB };

//    public static readonly byte[] data120 = { 0xAC, 0xAC, 0xAC, 0xAC };

//    public static readonly byte[] teachingCPRPlay = { 0xAD, 0xAD, 0xAD, 0xAD };

//    public static readonly byte[] openSubwayScene = { 0xC1, 0xC1, 0xC1, 0xC1 };
//    public static readonly byte[] openFireScene = { 0xC2, 0xC2, 0xC2, 0xC2 };
//    public static readonly byte[] openDrowningScene = { 0xC3, 0xC3, 0xC3, 0xC3 };
//    public static readonly byte[] openEarthquakeScene = { 0xC4, 0xC4, 0xC4, 0xC4};
//    public static readonly byte[] openTrafficAccidentScene = { 0xC5, 0xC5, 0xC5, 0xC5 };

//    public static readonly byte[] previewSubwayScene = { 0xB1, 0xB1, 0xB1, 0xB1 };
//    public static readonly byte[] previewFireScene = { 0xB2, 0xB2, 0xB2, 0xB2 };
//    public static readonly byte[] previewDrowningScene = { 0xB3, 0xB3, 0xB3, 0xB3 };
//    public static readonly byte[] previewEarthquakeScene = { 0xB4, 0xB4, 0xB4, 0xB4 };
//    public static readonly byte[] previewTrafficAccidentScene = { 0xB5, 0xB5, 0xB5, 0xB5 };
//    #endregion


//    #region pc Rturn 
//    public static readonly byte[] deviceNotReady = { 0xE0, 0xE0, 0xE0, 0xE0 };
//    public static readonly byte[] deviceReady = { 0xE1, 0xE1, 0xE1, 0xE1 };
//    public static readonly byte[] choosePanel = { 0xE2, 0xE2, 0xE2, 0xE2 };
//    public static readonly byte[] scenePanel = { 0xE3, 0xE3, 0xE3, 0xE3 };
//    public static readonly byte[] showTeachCPR = { 0xE4, 0xE4, 0xE4, 0xE4 };
//    public static readonly byte[] HideTeachCPR = { 0xE5, 0xE5, 0xE5, 0xE5 };
//    #endregion

//}
//[Serializable]
//public class ModelInfo
//{
//    public string modelID;
//    public bool isMainModel;
//    public string ipAddress;
//    public string port;
//    public bool connect;
//}
#endregion